:-include('chessRules').

weight(queen,9).
weight(rook,5).
weight(bishop,3).
weight(knight,3).
weight(pawn,1).
weight(king,0).
weight(threat,0.40).
weight(force,0.60).                                        
                                        


%evaluateForceCell(piece(Piece,Player),Player,Value):-weight(Piece,Value).
%evaluateForceCell(piece(Piece,Player),Turn,Value):-adversary(Player,Turn),weight(Piece,Val1),Value is Val1 * -1.
%evaluateForceCell(empty,_,0).
evaluateForceCell(empty,0).
evaluateForceCell(piece(Piece,white),Value):-weight(Piece,Value),!.
evaluateForceCell(piece(Piece,black),Value):-weight(Piece,Val1), Value is Val1 * -1.

%evaluateForceRow([H|T],Player,Value):-evaluateForceCell(H,Player,Val1),evaluateForceRow(T,Player,Val2),Value is Val1 + Val2.
evaluateForceRow([],_,0).
evaluateForceRow([H|T],Value):-evaluateForceCell(H,Val1),evaluateForceRow(T,Val2),Value is Val1 + Val2.

%evaluateForceBoard([],_,0).
%evaluateForceBoard([R|T],Player,Value):-evaluateForceRow(R,Player,Val1),evaluateForceBoard(T,Player,Val2), Value is Val1 + Val2.
evaluateForceBoard([],_,0).
evaluateForceBoard([R|T],Value):-evaluateForceRow(R,Val1),evaluateForceBoard(T,Val2), Value is Val1 + Val2.

%evaluateThreatBoard(Board,SS,Player,Value):-aggregate_all(sum(Value2),evaluateThreatBoard1(Board,SS,Player,Value2),Value).
%evaluateThreatBoard1(Board,SS,Player,Value):-ch_range(X),ch_range(Y),evaluateThreatCell(Board,SS,X,Y,Player,Value).
evaluateThreatBoard(Board,SS,Value):-aggregate_all(sum(Value2),evaluateThreatBoard1(Board,SS,Value2),Value).
evaluateThreatBoard1(Board,SS,Value):-ch_range(X),ch_range(Y),evaluateThreatCell(Board,SS,X,Y,Value).

%evaluateThreatCell(Board,SS,SX,SY,Player,Value):-aggregate_all(count, threat(Board,SS,SX,SY,TX,TY,Player), Count1),
%                                        adversary(Player,Player2),aggregate_all(count, threat(Board,SS,SX,SY,TX,TY,Player2), Count2),
%                                        bigger(Count1,Count2,Value).
%Probables Moves... fixit
%evaluateThreatCell(Board,SS,SX,SY,Value):-										aggregate_all(count, threat(BoardW,SS,SX,SY,TX,TY,white), Count1),
%                                        aggregate_all(count, threat(BoardB,SS,SX,SY,TX,TY,black), Count2),
%                                        bigger(Count1,Count2,Value).
evaluateThreatCell(Board,SS,SX,SY,Value):-rpMxT(Board,SX,SY,piece(pawn,black),BoardW),
										rpMxT(Board,SX,SY,piece(pawn,white),BoardB),
										aggregate_all(count, threat(BoardW,SS,SX,SY,TX,TY,white), Count1),
                                        aggregate_all(count, threat(BoardB,SS,SX,SY,TX,TY,black), Count2),
                                        bigger(Count1,Count2,Value).
                                        
evaluateBoard(Board,SS,-1000):-checkMate(Board,SS,white).
evaluateBoard(Board,SS,1000):-checkMate(Board,SS,black).
evaluateBoard(Board,SS,Value):-evaluateForceBoard(Board,Value1),evaluateThreatBoard(Board,SS,Value2),
                               weight(threat,W1),weight(force,W2),Value is Value1 * W1 + Value2 * W2.
										
bigger(A,B,Res):-A > B,Res is 1.
bigger(A,B,Res):-A < B, Res is -1.
bigger(A,B,_,Res):-A = B, Res is 0.										

alphaB(Deep,Board,SS,SX,SY,TX,TY,white):-
    alpha_beta(white,Deep,Board,SS,-2000,2000,SX,SY,TX,TY,_).

alpha_beta(_Player,0,Board,SS,_Alpha,_Beta,_NoSX,_NoSY,_NoTX,_NoTY,Value) :- 
   evaluateBoard(Board,SS,Value).

alpha_beta(Player,D,Board,SS,Alpha,Beta,SX,SY,TX,TY,Value) :- 
   D > 0, 
   findall((SX,SY,TX,TY,TB,TS),getMove(Board,SS,SX,SY,TB,TS,TX,TY,Player),Moves), 
   Alpha1 is -Beta, % max/min
   Beta1 is -Alpha,
   D1 is D-1, 
   evaluate_and_choose(Player,Moves,Board,D1,Alpha1,Beta1,nil,nil,nil,nil,(SX,SY,TX,TY,Value)).

evaluate_and_choose(Player,[(SX,SY,TX,TY,TB,TS)|Moves],Board,D,Alpha,Beta,RSX,RSY,RTX,RTY,BestMove) :-
   adversary(Player,OtherPlayer),
   alpha_beta(AlphaPlayer,OtherPlayer,D,TB,TS,Alpha,Beta,_OtherSX,_OtherSY,_OtherTX,_OtherTY,Value),
   Value1 is -Value,
   cutoff(AlphaPlayer,Player,SX,SY,TX,TY,TB,TS,Value1,D,Alpha,Beta,Moves,Board,RSX,RSY,RTX,RTY,BestMove).
evaluate_and_choose(_AP,white,[],_Position,_D,Alpha,_Beta,SX,SY,TX,TY,(SX,SY,TX,TY,Alpha)).
evaluate_and_choose(_AP,black,[],_Position,_D,_Alpha,Beta,SX,SY,TX,TY,(SX,SY,TX,TY,Beta)).

cutoff(_AP,_Player,SX,SY,TX,TY,_,_,Value,_D,_Alpha,Beta,_Moves,_Position,_RSX,_RSY,_RTX,_RTY,(SX,SY,TX,TY,Value)) :- 
   Value >= Beta, !.
cutoff(AP,Player,SX,SY,TX,TY,_,_,Value,D,Alpha,Beta,Moves,Position,_RSX,_RSY,_RTX,_RTY,BestMove) :- 
   Alpha < Value, Value < Beta, !, 
   evaluate_and_choose(AP,Player,Moves,Position,D,Value,Beta,SX,SY,TX,TY,BestMove).
cutoff(AlphaPlayer,Player,_SX,_SY,_TX,_TY,_TB,_TS,Value,D,Alpha,Beta,Moves,Position,RSX,RSY,RTX,RTY,BestMove) :- 
   Value =< Alpha, !, 
   evaluate_and_choose(AlphaPlayer,Player,Moves,Position,D,Alpha,Beta,RSX,RSY,RTX,RTY,BestMove).

